package p2pmodule;

import java.util.ArrayList;
import java.util.List;

import dustdispatcher.DispatchableTask;
import events.TransferFinishedListener;

/**
 * Class that represents a transfer from two (Dust) entities.
 * 
 * @author ole
 */
/** TODO: Debug needed here. What happen if we have to download lots of
 * images? It can occur when donwloaded a new RSS with lots of posts with
 * lots of images. Can it destroy the performance of the system?.
 * DispatchableTasks where created to avoid that situation but making
 * Transfer inherit from it and ServerTransfer and ClientTrasfer from
 * Transfer, can cause deadlock, think about this:
 * 
 * - Dust A found that Dust B has the files it (A) wants.
 * - Dust B found that Dust A has the files it (B) wants.
 * - Dust A create all its maximum DispatchableTasks to download from B.
 * - Dust B create all its maximum DispatchableTasks to download from A.
 * - Dust A receive connections from B so it creates the ServerTransfers but
 * 	 since maximum DispatchableTasks has been reached those ServerTransfers
 *   had to block.
 * - Dust B receive connections from A so it creates the ServerTransfers but
 * 	 since maximum DispatchableTasks has been reached those ServerTransfers
 *   had to block.
 * - Dust A ClientTransfers are waiting for ServerTransfers of B to be
 *   unblocked.
 * - Dust B ClientTransfers are waiting for ServerTransfers of A to be
 *   unblocked.
 * 
 * Tests have been done and, as predicted, making Transfers
 * not inherit from DispatchableTasks can freeze Dust (and the system) if it
 * tries to download too much files at a time (something common by the way). I
 * had returned back and make it inherit from DispatchableTask (and every place
 * using a Transfer start it DustDispatcher, not start(), and each Transfer
 * run() method at the end calls this.finalize()).
 * 
 * To avoid that situation we are using ServerTransfers as simple Threads, not
 * DispatchableThreads. I mean, when we create one we don't ask DustDispatcher
 * to run it when possible, we just call the start() method explicitly and at
 * the end of the the run() method of the ServerTransfer we don't call the
 * finalize() method (although it will be called by the garbage collector and
 * DustDispatcher will tell "Trying to remove a task that is not in the
 * queue").
 * **/
public abstract class Transfer extends DispatchableTask {
	// Class constants.
	protected final int MAX_FNAME = 1024;
	
	// Class attributes.
	protected List<TransferFinishedListener> tf_listeners;
	
	/**
	 * Class constructor.
	 */
	public Transfer() {
		tf_listeners = new ArrayList<TransferFinishedListener>();
	}
	
	/**
	 * Adds a new Listener for when the Transfer ends its work.
	 * 
	 * @param listener:
	 * 		The Listener to be executed at the end of the file transfer.
	 */
	public void addTransferFinishedListener(TransferFinishedListener listener) {
		tf_listeners.add(listener);
	}
	
	/**
	 * Method that must be implemented by subclasses for stop the transfer and
	 * finish its execution.
	 */
	public abstract void stopTransfer();
}
